<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import type { MessageProps } from './types';
	import { fly } from 'svelte/transition';
	import Icon from '$lib/components/Basic/Icon/Icon.svelte';
	import Portal from 'svelte-portal';
	import RectButton from '$lib/components/Basic/Button/RectButton.svelte';

	/* ===== 0. 真正的 props ===== */
	let {
		id,
		type = 'primary',
		message,
		duration = 2000,
		showClose = false,
		position = 'top',
		// index = 0,
		offset = 0,
		onClose
	}: MessageProps = $props();

	/* ===== 1. 派生常量 ===== */
	const TYPE_MAP = {
		primary: {
			icon: 'office/message',
			color: 'var(--color-primary-500)',
			bg: 'var(--color-primary-50)',
			border: 'var(--color-primary-200)'
		},
		success: {
			icon: 'symbol/check-circle',
			color: 'var(--color-success-500)',
			bg: 'var(--color-success-50)',
			border: 'var(--color-success-200)'
		},
		warning: {
			icon: 'symbol/warning',
			color: 'var(--color-warning-500)',
			bg: 'var(--color-warning-50)',
			border: 'var(--color-warning-200)'
		},
		info: {
			icon: 'office/message',
			color: 'var(--color-info-500)',
			bg: 'var(--color-info-50)',
			border: 'var(--color-info-200)'
		},
		error: {
			icon: 'symbol/cancel-circle',
			color: 'var(--color-error-500)',
			bg: 'var(--color-error-50)',
			border: 'var(--color-error-200)'
		}
	} as const;

	const config = $derived(TYPE_MAP[type]);
	const transitionOpts = $derived(
		position.startsWith('top')
			? { y: -20, duration: 300, opacity: 0 }
			: { y: 20, duration: 300, opacity: 0 }
	);

	/* ===== 2. 状态 ===== */
	let visible = $state(false);
	let timer: number | null = null;
	let el = $state<HTMLDivElement>();

	/* ===== 3. 生命周期 ===== */
	onMount(() => {
		visible = true;
		if (duration > 0) timer = window.setTimeout(close, duration);
	});

	onDestroy(() => {
		if (timer) clearTimeout(timer);
	});

	/* ===== 4. 关闭 ===== */
	const close = () => {
		visible = false;
	};

	/* ===== 5. 悬浮控制 ===== */
	const pause = () => timer && clearTimeout(timer);
	const resume = () => {
		if (duration > 0) timer = window.setTimeout(close, duration);
	};
</script>

<Portal target="body">
	{#if visible}
		<!-- 保证离场动画 -->
		<div
			bind:this={el}
			class="msg"
			data-position={position}
			data-id={id}
			class:side={!position.endsWith('center') && position !== 'top' && position !== 'bottom'}
			style:--bg={config.bg}
			style:--c={config.color}
			style:--bd={config.border}
			style:top={position.startsWith('top') ? `${offset}px` : 'auto'}
			style:bottom={position.startsWith('bottom') ? `${offset}px` : 'auto'}
			role="alert"
			aria-label={message}
			in:fly={{ ...transitionOpts, opacity: 1 }}
			out:fly={transitionOpts}
			onoutroend={onClose}
			onmouseenter={pause}
			onmouseleave={resume}
		>
			<Icon src={config.icon} size={16} color={config.color}></Icon>
			<div class="text">{@html message}</div>
			{#if showClose}
				<RectButton icon="symbol/close" onClick={close} type="link" variant={type} style="padding:0"></RectButton>
			{/if}
		</div>
	{/if}
</Portal>

<style scoped lang="scss">
	.msg {
		position: fixed;
		z-index: 9999;
		display: flex;
		align-items: center;
		gap: 8px;
		padding: 0 16px;
		height: 40px;
		max-width: 300px;
		border-radius: 8px;
		background: var(--bg);
		color: var(--c);
		border: 1px solid var(--bd);
		word-break: break-all;
		transition:
			top 0.3s ease,
			bottom 0.3s ease;
	}
	/* 水平定位 */
	.msg[data-position='top'],
	.msg[data-position='bottom'] {
		left: 50%;
		transform: translateX(-50%);
	}
	.msg[data-position='top-left'],
	.msg[data-position='bottom-left'] {
		left: 20px;
	}
	.msg[data-position='top-right'],
	.msg[data-position='bottom-right'] {
		right: 20px;
	}
	.text {
		flex: 1;
		font-size: 14px;
		line-height: 16px;
	}
</style>
